using System;

namespace Slaks.Readers
{
	using Slaks.Filters;

  public enum ReaderState { Term, MiddleSentencePunctuation, EndOfSentencePunctuation, SpecialCharacter, WhiteSpace, None }

	public abstract class AReader
	{
    /// <summary>
    /// Abstract filter
    /// </summary>
    protected AFilter m_filter = null;


    /// <summary>
    /// innner buffer holds characters that were detected but not linked to the current term
    /// for example in cases where there is a need to output punctuation marks, these characters
    /// will be put in inner buffer and then will be flushed after the term 
    /// </summary>
    protected char m_innerBuffer = char.MinValue;

    protected ReaderState m_innerBufferState = ReaderState.None;

    /// <summary>
    /// the state of reader operation
    /// </summary>
    protected ReaderState m_readerState = ReaderState.None;

    protected bool m_isOutputPunctuationMarks = true;

    protected bool m_isOutputSpecialCharacter = true;
    
    /// <summary>
    /// Constructor
    /// </summary>
    public AReader()
    {
			
    }

    /// <summary>
    /// Constructor 
    /// </summary>
    /// <param name="filter">abstract filter</param>
    public AReader(AFilter filter)
    {
      m_filter = filter;
    }
    
    public bool IsOutputPunctuationMarks
    {
      get { return m_isOutputPunctuationMarks; }
      set { m_isOutputPunctuationMarks = value; }
    }

    public bool IsOutputSpecialCharacter
    {
      get { return m_isOutputSpecialCharacter;}
      set { m_isOutputSpecialCharacter = value; }
    }

    /// <summary>
    /// Check for End of stream
    /// </summary>
    /// <returns>true/false</returns>
    public abstract bool Eof();
    
    /// <summary>
    /// Get the next term from the stream
    /// </summary>
    /// <param name="isEndOfSentence">marks the end of sentence after the term was read (in readers that implement this feature)</param>
    /// <returns>term</returns>
    public abstract string NextTerm(ref ReaderState state);

		/// <summary>
		/// Open the reader stream
		/// </summary>
		public abstract void OpenStream();

    /// <summary>
    /// Close the reader when finished
    /// </summary>
    public abstract void CloseReader();

    /// <summary>
    /// Get or Set filter\n
    /// Each reader must register instance of AFilter before starting reading stream
    /// </summary>
    /// <param name="filter">instance of AFilter</param>
    public AFilter Filter
    {
      get { return m_filter; }
      set { m_filter = value; }
    }

	}
}
